package com.wiscamp.ninechapters.tags.domain.services;

import com.wiscamp.ninechapters.tags.domain.TagsErrorCodes;
import com.wiscamp.ninechapters.tags.domain.models.Course;
import com.wiscamp.ninechapters.tags.domain.repositories.CourseRepository;
import cube.common.cache.CacheManagerNames;
import cube.ddd.aspect.HandleServiceException;
import cube.ddd.domain.BaseDomainService;
import cube.ddd.exception.ExceptionUtils;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Objects;

/**
 * Course Point Service
 *
 * @author yifeng
 */
@Service
public class CourseService extends BaseDomainService {

    private final CourseRepository courseRepository;

    private final String CACHE_NAME = "courses";

    public CourseService(CourseRepository courseRepository) {
        this.courseRepository = courseRepository;
    }

    //region course
    @Cacheable(value = CACHE_NAME, key = "#courseId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    @HandleServiceException
    public Course getCourse(@Min(0) long courseId) {
        var course = courseRepository.getCourse(courseId);
        if (Objects.isNull(course)) {
            ExceptionUtils.throwServiceException(TagsErrorCodes.COURSE_NOT_FOUND, courseId);
        }
        return course;
    }

    /*@HandleServiceException
    public Course getCourseByCode(@NotBlank String courseCode) {
        return courseRepository.getCourseByCode(courseCode);
    }

    @HandleServiceException
    public Collection<Course> getCoursesByName(@NotBlank String courseName) {
        return courseRepository.getCoursesByName(courseName);
    }

    @HandleServiceException
    public Collection<Course> getAvailableCourses() {
        return courseRepository.getAvailableCourses();
    }

    @HandleServiceException
    public PagedObjects<Course> getCoursesByQuery(@NotNull PagedQuery query) {
        return courseRepository.getCoursesByQuery(query);
    }*/

    @CachePut(value = CACHE_NAME, key = "#course.courseId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    @HandleServiceException
    public Course createCourse(@NotNull Course course, long operatorId) {
        var existedCourse = courseRepository.getCourseByCode(course.getCourseCode());
        if (Objects.nonNull(existedCourse)) {
            ExceptionUtils.throwServiceException(TagsErrorCodes.COURSE_CODE_EXISTED, course);
        }
        course.createBy(operatorId);
        return courseRepository.saveCourse(course);
    }

    @CachePut(value = CACHE_NAME, key = "#course.courseId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    @HandleServiceException
    public Course updateCourse(@NotNull Course course, long operatorId) {
        var existedCourse = getCourse(course.getCourseId());
        existedCourse = courseRepository.getCourseByCode(course.getCourseCode());
        if (Objects.nonNull(existedCourse) && existedCourse.getCourseId() != course.getCourseId()) {
            ExceptionUtils.throwServiceException(TagsErrorCodes.COURSE_CODE_EXISTED, course);
        }
        course.updateBy(operatorId);
        return courseRepository.saveCourse(course);
    }

    @CacheEvict(value = CACHE_NAME, key = "#courseId")
    @HandleServiceException
    public boolean deleteCourse(@Min(0) long courseId, long operatorId) {
        var course = getCourse(courseId);
        if (Objects.isNull(course)) return false;
        // 记录操作日志
        course.delete();
        course.updateBy(operatorId);
        courseRepository.saveCourse(course);
        return true;
    }

    @CacheEvict(value = CACHE_NAME, key = "#courseId")
    @HandleServiceException
    public boolean enableCourse(@Min(0) long courseId, long operatorId) {
        var course = getCourse(courseId);
        if (Objects.isNull(course)) return false;
        // 记录操作日志
        course.enable();
        course.updateBy(operatorId);
        courseRepository.saveCourse(course);
        return true;
    }

    @CacheEvict(value = CACHE_NAME, key = "#courseId")
    @HandleServiceException
    public boolean disableCourse(@Min(0) long courseId, long operatorId) {
        var course = getCourse(courseId);
        if (Objects.isNull(course)) return false;
        // 记录操作日志
        course.disable();
        course.updateBy(operatorId);
        courseRepository.saveCourse(course);
        return true;
    }

    // endregion

    // region outline

    // endregion
}
